home *** CD-ROM | disk | FTP | other *** search
/ EuroCD 3 / EuroCD 3.iso / Viewers / aMiPEG_1.0 / src / ham8.c < prev    next >
C/C++ Source or Header  |  1998-06-24  |  12KB  |  469 lines

  1. /*
  2.  *  This source copes with all amiga-specific stuff as opening the screen, resizing
  3.  *  it using user copper lists, etc.
  4.  *
  5.  *  Copper-based resizing is now implemented, although no aspect ratio is taken care of.
  6.  *
  7.  *  HAM6 is supported now.
  8.  *
  9.  *  Michael Rausch  14-4-94  1:11:59
  10.  *
  11.  *  Some fixes to allow for non-default monitors
  12.  *
  13.  *  Miloslaw Smyk  21-2-96
  14.  */
  15.  
  16. #include <proto/exec.h>
  17. #include <proto/intuition.h>
  18. #include <proto/graphics.h>
  19. #include <proto/asl.h>
  20.  
  21. #include <cybergraphics/cgxvideo.h>
  22. #include <pragmas/cgxvideo_pragmas.h>
  23. #include <clib/cgxvideo_protos.h>
  24.  
  25. #include <libraries/asl.h>
  26. #include <exec/memory.h>
  27. #include <hardware/custom.h>
  28. #include <graphics/copper.h>
  29. #include <graphics/gfxbase.h>
  30. #include <graphics/gfxmacros.h>
  31. #include <graphics/videocontrol.h>
  32. #include <graphics/displayinfo.h>
  33. #include <graphics/display.h>
  34.  
  35. #include <dos/dos.h>
  36. #include <proto/dos.h>
  37. #include <proto/asyncio.h>
  38.  
  39. #include <stdio.h>
  40. #include <stdlib.h>
  41. #include <string.h>
  42.  
  43. #include "video.h"
  44. #include "proto.h"
  45. extern int ditherType;
  46. extern int fullFlag;
  47.  
  48. extern void HAM8_Init(struct RastPort *);    // kinda static
  49. extern void HAM8_Init_lores(struct RastPort *);
  50. extern void HAM6_Init_lores(struct RastPort *);
  51.  
  52. void (*HAM8_draw)(void *, int, int);
  53.  
  54.  
  55. #define custom ((*(volatile struct Custom *)(0xdff000)))
  56.  
  57.  
  58. struct IntuitionBase *IntuitionBase;
  59. /* struct GfxBase *GfxBase; */
  60. extern struct ExecBase *SysBase;
  61. static struct Screen *screen;
  62. static ULONG soerror = NULL;
  63.  
  64. int gfxver;
  65. ULONG *kaiko = NULL;
  66.  
  67. int lores=TRUE, sdbl=TRUE, ham6=FALSE;
  68.  
  69. int max_x, max_y;
  70.  
  71. static struct ColorSpec firstblack[2]={ {0,0,0,0}, {-1, 0,0,0} };    /* Color 0 is 0x000*/
  72.  
  73.  
  74. static void Quit(char *why, int failcode)
  75. {
  76.     puts(why);
  77.     exit(failcode);
  78. }
  79.  
  80. static void output_term(void)
  81. {
  82.     close_timer();
  83.  
  84.     if(input)
  85.     {
  86.         CloseAsync(input);
  87.         input = NULL;
  88.     }
  89.  
  90.     if (screen)
  91.     {
  92.         FreeVPortCopLists(&(screen->ViewPort));
  93.         RemakeDisplay();
  94.  
  95.         if(cyber_window)
  96.             CloseWindow(cyber_window);
  97.  
  98.         CloseScreen(screen);
  99.     }
  100.     if (IntuitionBase) CloseLibrary((struct Library *) IntuitionBase);
  101.     if (GfxBase) CloseLibrary((struct Library *) GfxBase);
  102. }
  103.  
  104.  
  105. int get_ham_modeid(void)
  106. {
  107.     struct ScreenModeRequester *scrMdReq;
  108.     int modeid = 0xffffffff;
  109.  
  110.     if(scrMdReq = AllocAslRequestTags(ASL_ScreenModeRequest,
  111.                                                                         ASLSM_MinWidth, 200,
  112.                                                                         ASLSM_MinHeight, 200,
  113.                                                                         ASLSM_MinDepth, 6,
  114.                                                                         ASLSM_MaxDepth, 8,
  115.                                                                         ASLSM_PropertyFlags, DIPF_IS_HAM,
  116.                                                                         ASLSM_PropertyMask, DIPF_IS_HAM,
  117.                                                                         TAG_DONE))
  118.     {
  119.         if(AslRequestTags(scrMdReq, TAG_DONE))
  120.             modeid = scrMdReq->sm_DisplayID;
  121.  
  122.         FreeAslRequest(scrMdReq);
  123.     }
  124.  
  125.     return(modeid);
  126. }
  127.  
  128.  
  129. void InitColorDisplay(void)
  130. {
  131.     atexit(output_term);
  132.  
  133.     if ((GfxBase=(struct GfxBase *) OpenLibrary("graphics.library",37))==NULL)
  134.         Quit("graphics.library is too old, <V39",25);
  135.     if ((IntuitionBase=(struct IntuitionBase *) OpenLibrary("intuition.library",37))==NULL)
  136.         Quit("intuition.library is too old, <V39",25);
  137.  
  138.     gfxver = GfxBase->LibNode.lib_Version;
  139.     if(gfxver>=40) kaiko = GfxBase->ChunkyToPlanarPtr;
  140.  
  141.     HAM8_draw = (void (*)(void *, int, int)) NoDitherImage;    // method casting ... argh!
  142.     DoDitherImage = NoDitherImage;
  143.  
  144.     if((modeid == 0xffffffff) && ((modeid = get_ham_modeid()) == 0xffffffff))
  145.         Quit("aMiPEG: unable to open HAM display...", 25);
  146. }
  147.  
  148.  
  149. /*
  150.  *   Resize the display using a copper list. Nifty'n neat amiga feature.
  151.  *
  152.  *   Phew ... takes now 2 hours to fiddle the system-compliant custom modulo stuff.
  153.  */
  154. void ResizeDisplay(int w, int h)
  155. {
  156.     struct UCopList *ucoplist;
  157.     static struct TagItem uCopTags[] = {
  158.         { VC_NoColorPaletteLoad, TRUE },
  159.         { VTAG_USERCLIP_SET, NULL },
  160.         { VTAG_END_CM, NULL }};
  161.     int i,j,k, y, fp_each, locallores;
  162.     struct CopList *dspins;
  163.     struct CopIns *copins;
  164.     short bpl1mod=-1, bpl2mod=-1, last1, last2, this1, this2;
  165.     ULONG id;
  166.     struct DimensionInfo dim_info;
  167.     BOOL quit = FALSE;
  168.     struct IntuiMessage *msg;
  169.     static char win_title[256];
  170.     static VLH_x, VLH_y;
  171.     static char first_time = TRUE;
  172.  
  173.     if(ditherType == NO_DITHER) return;
  174.  
  175.     if(ditherType == CYBERGFX_DITHER || ditherType == CYBERGFXGRAY_DITHER || ditherType == GRAY_DITHER || ditherType == CYBERGFXVLAYER_DITHER || ditherType == CYBERGFXVLAYERGRAY_DITHER)
  176.     {
  177.         if(ditherType == CYBERGFXVLAYER_DITHER || ditherType == CYBERGFXVLAYERGRAY_DITHER)
  178.         {
  179.             if(VLH && (VLH_x != w || VLH_y != h))
  180.             {
  181.                 DetachVLayer(VLH);
  182.                 DeleteVLayerHandle(VLH);
  183.                 VLH = NULL;
  184.             }
  185.  
  186.             if(!VLH && (VLH = CreateVLayerHandleTags(cyber_screen,
  187.                                                                             VOA_SrcType, SRCFMT_YCbCr16,
  188.                                                                             VOA_SrcWidth, w,
  189.                                                                             VOA_SrcHeight, h,
  190.                                                                             TAG_DONE)))
  191.             {
  192.                 if(AttachVLayerTags(VLH, cyber_window, TAG_DONE))
  193.                     Quit("Unable to attach video layer to a window", 25);
  194.             }
  195.             else
  196.                 Quit("Unable to create a video layer", 25);
  197.  
  198.         }
  199.  
  200.         sprintf(win_title, "%s [%dx%d]", FilePart(animname), w, h);
  201.         SetWindowTitles(cyber_window, win_title, (UBYTE *)~0);
  202.  
  203.         if(!fullFlag && first_time)
  204.         {
  205.             first_time = FALSE;
  206.  
  207.             ModifyIDCMP(cyber_window, IDCMP_NEWSIZE);
  208.  
  209. //            SizeWindow(cyber_window, w - 160, h - 120);
  210.       ChangeWindowBox(cyber_window, cyber_window->LeftEdge, cyber_window->TopEdge,
  211.                                                 w + cyber_window->BorderLeft + cyber_window->BorderRight,
  212.                                                 h + cyber_window->BorderTop + cyber_window->BorderBottom);
  213.  
  214.             while(!quit)
  215.             {
  216.                 WaitPort(cyber_window->UserPort);
  217.                 while(msg = (struct IntuiMessage *)GetMsg(cyber_window->UserPort))
  218.                 {
  219.                     if(msg->Class == IDCMP_NEWSIZE)
  220.                         quit = TRUE;
  221.  
  222.                     ReplyMsg((struct Message *)msg);
  223.                 }
  224.             }
  225.  
  226.             ModifyIDCMP(cyber_window, CLOSEWINDOW | MOUSEBUTTONS | VANILLAKEY);
  227.  
  228.             original_x = cyber_window->Width;
  229.             original_y = cyber_window->Height;
  230.         }
  231.         else
  232.             if(!first_time)
  233.             {
  234.                 original_x = w;
  235.                 original_y = h;
  236.             }
  237.  
  238.         return;
  239.     }
  240.  
  241.     id = modeid & MONITOR_ID_MASK;
  242.  
  243.     if (GetDisplayInfoData(FindDisplayInfo(id), (UBYTE *)&dim_info, sizeof(struct DimensionInfo), DTAG_DIMS, 0))
  244.         max_y=dim_info.StdOScan.MaxY - dim_info.StdOScan.MinY + 1;
  245.     else
  246.         max_y=200;
  247.  
  248.     if(h>max_y)
  249.         sdbl=FALSE, max_y<<=1;
  250.  
  251.     if(!(GfxBase->ChipRevBits0 & (GFXF_AA_ALICE|GFXF_AA_LISA)))
  252.         ham6 = TRUE;
  253.  
  254.     if(ham6)
  255.         lores=TRUE;
  256.     locallores = lores && (w<=160);
  257.     max_x = (locallores ? 320 : 640);
  258.  
  259.     switch(id)
  260.     {
  261.         case A2024_MONITOR_ID:
  262.             Quit("Get some colors, dude.", 25);
  263.  
  264.         case DBLPAL_MONITOR_ID: /* ARGH!  Kick their butts for this one! */
  265.             if(sdbl)
  266.                 id = locallores ? DBLPALLORESHAMFF_KEY : DBLPALHIRESHAMFF_KEY;
  267.             else
  268.                 id = locallores ? DBLPALLORESHAM_KEY : DBLPALHIRESHAM_KEY;
  269.             break;
  270.  
  271.         case DBLNTSC_MONITOR_ID:
  272.             if(sdbl)
  273.                 id = locallores ? DBLNTSCLORESHAMFF_KEY : DBLNTSCHIRESHAMFF_KEY;
  274.             else
  275.                 id = locallores ? DBLNTSCLORESHAM_KEY : DBLNTSCHIRESHAM_KEY;
  276.             break;
  277.  
  278.         case EURO72_MONITOR_ID:
  279.             if(sdbl)
  280.                 id = locallores ? EURO72LORESHAMDBL_KEY : EURO72PRODUCTHAMDBL_KEY;
  281.             else
  282.                 id = locallores ? EURO72LORESHAM_KEY : EURO72PRODUCTHAM_KEY;
  283.             break;
  284.  
  285.         case VGA_MONITOR_ID:
  286.             if(sdbl)
  287.                 id = locallores ? VGALORESHAMDBL_KEY : VGAPRODUCTHAMDBL_KEY;
  288.             else
  289.                 id = locallores ? VGALORESHAM_KEY : VGAPRODUCTHAM_KEY;
  290.             break;
  291.  
  292.         case PAL_MONITOR_ID:
  293.         case NTSC_MONITOR_ID:
  294. /*
  295.             if(gfxver >= 40 && sdbl)
  296.                 id = locallores ? id | LORESHAMSDBL_KEY: id | HIRESHAMSDBL_KEY;
  297.             else
  298. */
  299.                 sdbl=FALSE, id = locallores ? id | HAM_KEY : id | HIRESHAM_KEY;
  300.             break;
  301.  
  302.         default:
  303.             printf("ModeID 0x%x either doesn't support HAM or is unknown to aMiPEG.", id);
  304.             Quit("", 10);
  305.     }
  306.  
  307.     if(!(screen=OpenScreenTags(NULL,
  308.         SA_DisplayID,    id,
  309.         SA_Depth,    ham6?6:8,
  310.         SA_Width,    max_x,
  311.         SA_Colors,    firstblack,
  312.         SA_Type,    CUSTOMSCREEN|SCREENQUIET,
  313.         SA_Quiet,     TRUE,
  314.         SA_Interleaved,    !ham6, //TRUE,
  315.         SA_Overscan,    OSCAN_STANDARD,
  316.         SA_MinimizeISG,    TRUE,
  317.         SA_ErrorCode,    &soerror,
  318.         TAG_END))) Quit("Couldn't open screen.",25);
  319.  
  320.     if((screen->RastPort.BitMap->Depth == 6) && !ham6)
  321.         Quit("Incorrect depth. Please try to specify \"-dither ham6\" explicitely.",25);
  322.  
  323.                 if(cyber_window = OpenWindowTags(NULL,
  324.                                     WA_CustomScreen, screen,
  325.                                     WA_Flags, WFLG_ACTIVATE | WFLG_BORDERLESS | WFLG_BACKDROP,
  326.                     WA_IDCMP, VANILLAKEY,
  327.                     TAG_DONE))
  328.                     ;
  329.  
  330.     if(lores) {
  331.         if(ham6)
  332.         {    // the new ham6 routines do not handle interleaved bitmaps anymore
  333.             HAM6_Init_lores(&(screen->RastPort));
  334.             HAM8_draw = HAM6_draw_lores;
  335.             DoDitherImage = ColorDitherImage_12bit;
  336.         } else {
  337.             HAM8_Init_lores(&(screen->RastPort));
  338.             HAM8_draw = HAM8_draw_lores;
  339.             DoDitherImage = ColorDitherImage_lores;    // lacks kaiko support, actually
  340.         }
  341.         max_x >>=1;
  342.  
  343.     } else {
  344.         HAM8_Init(&(screen->RastPort));
  345.         HAM8_draw = HAM8_draw_hires;
  346.         DoDitherImage = ColorDitherImage;    // kaiko on one day
  347.         max_x >>=2;
  348.     }
  349.  
  350.     if(noDisplayFlag)
  351.         HAM8_draw = (void (*)(void *, int, int)) NoDitherImage;    // method casting ... argh!
  352.  
  353.  
  354.     /* the memory is freed upon exit in output_term via FreeVPortCopLists */
  355.     if(!(ucoplist = AllocMem(sizeof(struct UCopList), MEMF_PUBLIC|MEMF_CLEAR)))
  356.         Quit("No memory for copper list.",25);
  357.  
  358.     /* fiddle out some hardware values from this screen's init copper list */
  359.     dspins=screen->ViewPort.DspIns;
  360.     copins=dspins->CopIns;
  361.     for(i=dspins->Count-1; i>=0; i--, copins++)
  362.     {
  363.         j = copins->DESTDATA;
  364.  
  365.         switch(copins->DESTADDR & 0xfff)    // argh! kick 2.1 messes this up!
  366.         {        
  367.             case (int)&((*(struct Custom *)(0)).bpl1mod):
  368.                 last1=bpl1mod = j;
  369.                 break;
  370.             case (int)&((*(struct Custom *)(0)).bpl2mod):
  371.                 last2=bpl2mod = j;
  372.                 break;
  373.         }
  374.     }
  375.  
  376.     if(bpl1mod==-1 || bpl2mod==-1)
  377.     {
  378.         printf("ooops\n");
  379.         return;    /* hmmm? */
  380.     }
  381.  
  382.     if((bpl1mod == bpl2mod) && sdbl) sdbl=FALSE;
  383.  
  384.     y = screen->Height;
  385.     (void) CINIT(ucoplist, y*3);        /* ... instructions per line */
  386.  
  387.  
  388.     if(sdbl)
  389.     {
  390.         /*
  391.          *  We abuse some of AGA's features here; double-scanning is implemented
  392.          *  by applying bpl1mod to ALL planes on one line, bpl2mod on the next.
  393.          *  Obviously, double-scanning enables some kind of internal chipmem cache.
  394.          *  At least, it's faster. And (because of?) less copper instructions.
  395.          */
  396.  
  397.         fp_each = ((y*2)<<8) / (short)h;
  398.         for(k=fp_each, j=0; j<y; j++)                /* for each line in the display */
  399.         {
  400.  
  401.             if((k-=0x100)>=0x100)                /* we still gotta double the line */
  402.                 this1=bpl1mod;
  403.             else                        /* finally, we are ready; next one */
  404.                 this1=bpl2mod, k=(k&0xff)+fp_each;
  405.  
  406.             if((k-=0x100)>=0x100)                /* we still gotta double the line */
  407.                 this2=bpl1mod;
  408.             else                        /* finally, we are ready; next one */
  409.                 this2=bpl2mod, k=(k&0xff)+fp_each;
  410.  
  411.             if(last1!=this1 || last2!=this2)
  412.                 CWAIT(ucoplist, j, 0);
  413.  
  414.             if(last1!=this1)
  415.             {
  416.                 CMOVE(ucoplist, custom.bpl1mod, this1);
  417.                 last1=this1;
  418.             }
  419.  
  420.             if(last2!=this2)
  421.             {
  422.                 CMOVE(ucoplist, custom.bpl2mod, this2);
  423.                 last2=this2;
  424.             }
  425.         }
  426.     } else {
  427.         /*
  428.          *  No scan-doubling possible; most probably because of a pal/ntsc screen 
  429.          *  and no V40 graphics library available.
  430.          */
  431.  
  432.         bpl1mod -= screen->RastPort.BitMap->BytesPerRow;
  433.  
  434.         fp_each = (y<<8) / (short)h;
  435.         for(k=fp_each, j=0; j<y; j++)                /* for each line in the display */
  436.         {
  437.  
  438.             if((k-=0x100)>=0x100)                /* we still gotta double the line */
  439.                 this1=bpl1mod;
  440.             else                        /* finally, we are ready; next one */
  441.                 this1=bpl2mod, k=(k&0xff)+fp_each;
  442.  
  443.             if(last1!=this1)
  444.             {
  445.                 CWAIT(ucoplist, j, 0);
  446.                 CMOVE(ucoplist, custom.bpl1mod, this1);
  447.                 CMOVE(ucoplist, custom.bpl2mod, this1);
  448.                 last1=this1;
  449.             }
  450.         }
  451.     }
  452.  
  453.     /*
  454.      *  Pretty nifty, isn't it? Finally, even a little bit copper-list-optimizing is build in!
  455.      */
  456.  
  457.     CEND(ucoplist);
  458.  
  459.     /* Set the freshly created user copper list */
  460.     //Forbid();
  461.     screen->ViewPort.UCopIns = ucoplist;
  462.     //Permit();
  463.  
  464.     /*  Enable user copper list clipping for this ViewPort.  */
  465.     (void) VideoControl( screen->ViewPort.ColorMap, uCopTags );
  466.  
  467.     RethinkDisplay();
  468. }
  469.